package auth

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"gitee.com/hexug/go-tools/ioc"
	"gitee.com/hexug/go-tools/ioc/jwt"
	"gitee.com/hexug/go-tools/logger"
	"github.com/gin-gonic/gin"
)

var secret *jwt.Jwt

func init() {
	secret = ioc.Container.GetConf(jwt.ConfName).(*jwt.Jwt)
}

func ValidateSignature(token, timestampStr, signature string, maxTimeDiff int) (bool, error) {
	// 1. 验证时间戳是否有效
	timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
	if err != nil {
		logger.L().Failf("无效的时间戳格式: %v", err)
		return false, fmt.Errorf("无效的时间戳格式: %v", err)
	}

	// 检查时间戳是否在有效范围内
	now := time.Now().Unix()
	if timestamp < now-int64(maxTimeDiff) || timestamp > now+int64(maxTimeDiff) {
		logger.L().Failf("时间戳超出有效范围，当前时间: %d, 请求时间: %d", now, timestamp)
		return false, fmt.Errorf("时间戳超出有效范围，当前时间: %d, 请求时间: %d", now, timestamp)
	}

	// 2. 重新计算签名
	signStr := fmt.Sprintf("%s%s%s", timestampStr, token, timestampStr)
	hash := sha256.Sum256([]byte(signStr))
	computedSignature := hex.EncodeToString(hash[:]) // 转换为小写十六进制

	// 3. 比较签名是否一致
	if computedSignature != signature {
		logger.L().Failf("签名不匹配，计算得到: %s, 请求提供: %s", computedSignature, signature)
		return false, fmt.Errorf("签名不匹配，计算得到: %s, 请求提供: %s", computedSignature, signature)
	}

	return true, nil
}

func AuthMiddleware(c *gin.Context) {
	// 从请求头中获取参数
	timestamp := c.Request.Header.Get("timestamp")
	signature := c.Request.Header.Get("signature")
	serverToken := secret.SecretKey // 服务器端保存的Token，应与客户端一致

	// 验证签名
	valid, err := ValidateSignature(serverToken, timestamp, signature, 180)
	if !valid || err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"code": "401", "message": "Unauthorized"})
		logger.L().Failf("签名验证失败: %v", err)
		c.Abort()
		return
	}

	logger.L().Success("通过校验")
	c.Next()
}
